package JavaSE;

import java.util.ArrayList;
import java.util.Scanner;

public class time_20250415运算符练习 {
    //使用数组写一个方法返回多个数值
    public static int[] performOperations(int x,int y){
        int sum = x+y;
        int difference = x-y;
        int product = x*y;
        int quotient = x/y;
        int remainer = x%y;
        return new int[]{sum,difference,product,quotient,remainer};
        //关于return语句里的new:在Java中，new关键字用于创建一个新的对象或数组实例。当你使用new关键字时，你是在请求Java虚拟机为你分配内存来存储新的对象或数组。
        /*new int[]{...}是在创建一个新的int数组实例，并立即用大括号{}中的值初始化它。这个数组是匿名的，因为它没有变量名，直接在new关键字后面定义并初始化。*/
    }


    //编写一个内部类，然后用内部类内部的静态方法进行计算器的四则运算
    class Calculator{
        //注意，这里没有publi,不能写public，
        // 如果一定要用public的话需要在JavaSE包内重新创建Calculator类，
        // 其实写在 (time_20250415运算符练习) 这个类外也是也可以的，这个时候就是非内部类，
        // 但是Calculator这个类也是只能 (time_20250415运算符练习) 这个类使用的
        public static double add(double a,double b){
            return a+b;
        }

        public static double difference(double a,double b){
            return a -b;
        }

        public static double product(double a,double b){
            return a*b;
        }

        public static double quotient(double a,double b){
            return b!=0?a/b:0;
        }
    }

    //直接定义一个方法，然后返回一个数组，在方法里使用数组存储四则运算的结果
    public static double[] ResultCalculator(double a,double b){
        double[] ResultArray = {(a+b),(a-b),(a*b),(b!=0?a/b:0)};
        return ResultArray;
    }

    //实现阶乘的方法
    public static int fac(int number){
        int sum = 1;
        while(number>1){
            sum *= number;
            number = number -1;
        }
        return sum;
    }

    //写一个函数，该函数接受一个整数参数，并返回该整数的所有素数因子。
    //补充:素数因子（Prime Factor）是一个数的素数因子，是指能够整除该数且本身是素数的因子
    //判断一个数是否为素数？只能被1和其本身整除,但是1不是素数
    public static ArrayList<Integer> PrimeResult(int num){
        ArrayList<Integer> result = new ArrayList<>();

        if(num == 2){
            result.add(2);
            return result;
        }
        for(int i = 1;i <=num;i++){
            if((num%i==0)&&Prime(i)){
                if(i == 1){
                    continue;
                }
                result.add(i);
            }
        }
        return result;
    }

    //先写一个方法判断一个数是否为素数
    public static boolean Prime(int num) {
        int count = 0;
        if (num == 2) {
            return true;
        } else if (num <= 0) {
            //System.out.println("您输入的数有误，请重新输入！");
            return false;
        } else {
            for (int i = 2; i < num; i++) {
                if (num % i == 0) {
                    count++;
                }
            }
            if (count == 0) {
                return true;
            } else {
                return false;
            }
        }
    }

    public static void main(String[] args){
             /*
            1.算术运算符练习
            编写一个Java程序，实现一个函数，该函数接受两个整数参数，并返回它们的和、差、乘积、商和余数。
            编写一个Java程序，计算并输出从1到100（包含100）所有整数的和。
            */

            //编写一个Java程序，实现一个函数，该函数接受两个整数参数，并返回它们的和、差、乘积、商和余数。
            //仅仅使用一个普通的方法无法实现一次性返回多个值，如果想要实现一次性返回多个值，有以下五种办法
             //法一：使用数组：返回一个包含所有结果的数组。
//            int a = 10;
//            int b = 5;
//            int[] result1 = performOperations(a,b);
//            System.out.println("和: " + result1[0]);
//            System.out.println("差: " + result1[1]);
//            System.out.println("乘积: " + result1[2]);
//            System.out.println("商: " + result1[3]);
//            System.out.println("余数: " + result1[4]);
            //法二：使用类或对象：创建一个类来存储所有结果，然后返回这个类的实例。在ArithmeticOperations1类中写了

            //法三：使用泛型类：如Pair或Triple等，根据需要返回的值数量选择。没学到，暂时不做

            //法四：使用Map：返回一个Map，其中键是结果的名称，值是结果本身。没学到，暂时不做
            //法五：使用ArrayList，详细查看类--运算符练习之使用ArrayList同时返回多个值

            /*
            2.关系运算符练习
            编写一个Java程序，判断一个整数是否为偶数，并输出相应的信息。
            编写一个Java程序，接受三个整数参数，并判断这三个数是否能构成一个三角形（任意两边之和大于第三边）。
            */
        //编写一个Java程序，判断一个整数是否为偶数，并输出相应的信息。
//            System.out.print("请您输入一个整数:");
//            Scanner scanner = new Scanner(System.in);
//            int num = scanner.nextInt();
//            if(num%2==0){
//                System.out.println("您输入的数是偶数");
//            }else{
//                System.out.println("您输入的数是奇数");
//            }
//        //编写一个Java程序，接受三个整数参数，并判断这三个数是否能构成一个三角形（任意两边之和大于第三边）。
//        Scanner scanner = new Scanner(System.in);
//        System.out.println("请您输入三个正整数:");

//        int a = scanner.nextInt();
//        int b = scanner.nextInt();
//        int c = scanner.nextInt();
//        //三角形任意两边之和大于第三边，任意两边之差小于第三边，s,b,c均大于0
//        if((a+b>c)&&(a+c>b)&&(b+c>a)&&(a-b)<c&&(a-c<b)&&(b-c)<a&&(a>0)&&(b>0)&&(c>0)){
//            System.out.println("您输入的三个整数可以构成一个三角形！");
//        }else{
//            System.out.println("您输入的这三个正整数不能构成一个三角形！");
//        }
             /*
            3.逻辑运算符练习
            编写一个Java程序，判断一个年份是否为闰年。闰年的条件是：能被4整除但不能被100整除，或者能被400整除。
            编写一个Java程序，接受一个整数参数，并判断该整数是否在10到100之间（包含10和100）。
            */
//        //编写一个Java程序，判断一个年份是否为闰年。闰年的条件是：能被4整除但不能被100整除，或者能被400整除。
//            Scanner scanner = new Scanner(System.in);
//            System.out.print("请您输入一个年份:");
//            int year = scanner.nextInt();
//            if(((year%4==0)&&(year%100!=0))||(year%400==0)){
//                System.out.println("您输入的年份为闰年!");
//            }else{
//                System.out.println("您输入的年份不是闰年！");
//            }
//            //编写一个Java程序，接受一个整数参数，并判断该整数是否在10到100之间（包含10和100）。
//            System.out.print("请您输入一个整数:");
//            int number = scanner.nextInt();
//            if((number>=10)&&(number<=100)){
//                System.out.println("您输入的数在10到100之间🙂");
//            }

            /*4.位运算符练习
            编写一个Java程序，使用位运算符实现两个整数的交换，不使用临时变量。
            编写一个Java程序，计算一个整数的二进制表示中1的个数。
            */
            //编写一个Java程序，使用位运算符实现两个整数的交换，不使用临时变量。
            /*
            位运算符中的异或运算符（^）在这里起到了关键作用。异或运算有以下特性：
            任何数和0进行异或运算，结果仍然是原来的数，即 x ^ 0 = x。
            任何数和自身进行异或运算，结果为0，即 x ^ x = 0。
            异或运算满足交换律和结合律，即 a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c。

            基于这些特性，我们可以通过以下步骤交换两个数 a 和 b 的值：
            a = a ^ b：此时 a 的值变成了 a 和 b 的异或结果。
            b = a ^ b：由于 a 现在是 a 和 b 的异或结果，所以 b 变成了 a ^ b ^ b，根据异或的特性，这等于 a（因为 b ^ b = 0，所以 a ^ 0 = a）。
            a = a ^ b：现在 b 是原来的 a，所以 a 变成了 a ^ b，即 a ^ a（因为 b 现在是原来的 a），根据异或的特性，这等于 b。
            通过这三步，我们成功地交换了 a 和 b 的值，而没有使用任何临时变量。
            */
//            int a = 10;
//            int b = 20;
//            System.out.println("交换前:a="+a+",b="+b);
//            //交换a和b的值
//            a = a^b;
//            b = a^b;//b = (a^b)^b=a^0=a
//            a = a^b;//a = (a^b)^b = a^b^a = a^a^b = 0^b = b
//            System.out.println("交换后:a="+a+",b="+b);

            //编写一个Java程序，计算一个整数的二进制表示中1的个数。
//            Scanner scanner = new Scanner(System.in);
//        System.out.print("请您输入您要计算的整数:");
//            int num = scanner.nextInt();
//            int count = 0;
//            while(num>0){
//                if((num&1)==1){
//                    count++;
//                }
//                num = num >>> 1;
//            }
//        System.out.println("您要计算的整数的二进制位有"+count+"个1😊😊");
            /*这个程序使用了位运算来计算一个整数的二进制表示中1的个数。具体原理如下：
            位与运算（&）：
            n & 1 用于检查数字 n 的最低位是否为1。如果最低位是1，则 n & 1 的结果为1，否则为0。这样我们可以知道每次循环中最低位是否为1，并为计数器相应地增加1。

            无符号右移（>>>）：
            n >>> 1 用于将数字 n 的所有位都向右移动一位，最低位被移出，最高位补0。这样每次循环后，我们都会检查下一个位是否为1。

            循环：
            循环继续进行，直到 n 变为0。每次循环都会检查并计数最低位的1，然后右移一位。当 n 为0时，所有的位都已经检查完毕，循环结束。*/

            //扩展：将一个整数转化为二进制数然后输出该整数的二进制形式

            /*
            5.条件运算符练习
            编写一个Java程序，使用条件运算符（三元运算符）找出两个整数中的较大值，并输出。
            编写一个Java程序，接受一个整数参数，并使用条件运算符判断该整数是正数、负数还是零，并输出相应的信息。
            */
//            Scanner scanner = new Scanner(System.in);
//            System.out.println("请输入两个整数:");
//            int a = scanner.nextInt();
//            int b = scanner.nextInt();
//            System.out.println(a>b?a:b);
//              System.out.println("请输入一个整数:");
//              int num = scanner.nextInt();
//              System.out.println(num>0?"您输入的整数是正数":num==0?"您输入的整数是0":"您输入的整数是负数");
            /*
            6.算法相关练习
            编写一个Java程序，实现一个简单的计算器，可以执行加、减、乘、除四种基本运算。
            编写一个Java程序，实现一个函数，该函数接受一个整数参数，并返回该整数的阶乘。
            编写一个Java程序，实现一个函数，该函数接受一个整数参数，并返回该整数的所有素数因子。
            编写一个Java程序，实现Fibonacci数列的前n项计算，并输出结果。
            */
//            //编写一个Java程序，实现一个简单的计算器，可以执行加、减、乘、除四种基本运算。
        //法一：编写一个类，类里用静态方法实现四则运算的计算器，然后在main函数里直接  类名.静态方法名(参数列表)  即可调用计算器实现四则运算
//            Scanner scanner = new Scanner(System.in);
//            System.out.println("请您输入两个浮点数:");
//            double num1 = scanner.nextDouble();
//            double num2 = scanner.nextDouble();
//            System.out.println("两数之和为:"+Calculator.add(num1,num2));
//            System.out.println("两数之差为:"+Calculator.difference(num1,num2));
//            System.out.println("两数之积为:"+Calculator.product(num1,num2));
//            System.out.println("两数之商为:"+Calculator.quotient(num1,num2));
//
//            //输入整型数据会自动被转化为浮点型数据
//            System.out.println("请您输入两个整数:");
//            int num3 = scanner.nextInt();
//            int num4 = scanner.nextInt();
//            System.out.println("两数之和为:"+Calculator.add(num3,num4));
//            System.out.println("两数之差为:"+Calculator.difference(num3,num4));
//            System.out.println("两数之积为:"+Calculator.product(num3,num4));
//            System.out.println("两数之商为:"+Calculator.quotient(num3,num4));
//        //法二：直接定义一个方法，然后返回一个数组，在方法里使用数组存储四则运算的结果
//        Scanner scanner = new Scanner(System.in);
//        System.out.println("请您输入您要计算的两个数:");
//        double num1 = scanner.nextDouble();
//        double num2 = scanner.nextDouble();
//        double[] result_array1 =ResultCalculator(num1,num2);
//        System.out.println("这两个数的和为:"+result_array1[0]);
//        System.out.println("这两个数的差为:"+result_array1[1]);
//        System.out.println("这两个数的积为:"+result_array1[2]);
//        System.out.println("这两个数的商为:"+result_array1[3]);
//        System.out.println("请您输入您要计算的两个数:");
//        int num3 = scanner.nextInt();
//        int num4 = scanner.nextInt();
//        double[] result_array2 =ResultCalculator(num3,num4);//这里返回值是double类型的，所以数组必须定义为double类型的数组，定义为int类型的会报错，但是输入的数就可以定义为int，会自动被转换成double的
//        System.out.println("这两个数的和为:"+result_array2[0]);
//        System.out.println("这两个数的差为:"+result_array2[1]);
//        System.out.println("这两个数的积为:"+result_array2[2]);
//        System.out.println("这两个数的商为:"+result_array2[3]);
//
//        //编写一个Java程序，实现一个函数，该函数接受一个整数参数，并返回该整数的阶乘。
//        Scanner scanner = new Scanner(System.in);
//        System.out.print("请您输入一个整数:");
//        int num = scanner.nextInt();
//        System.out.println("您输入的数的阶乘为:"+fac(num));
//
//        //编写一个Java程序，实现一个函数，该函数接受一个整数参数，并返回该整数的所有素数因子。
//        //补充:素数因子（Prime Factor）是一个数的素数因子，是指能够整除该数且本身是素数的因子,但是这个数不一定是素数！！！！
//        //判断一个数是否为素数？只能被1和其本身整除
//        Scanner scanner = new Scanner(System.in);
//        System.out.print("请您输入一个整数:");
//        int num = scanner.nextInt();
//        ArrayList<Integer> prime_result =PrimeResult(num);
//        if(prime_result.size()==0){
//            System.out.println("您输入的数没有素数因子！");
//        }else {
//            for (int i = 0; i < prime_result.size(); i++) {
//                System.out.println(prime_result.get(i));
//            }
//        }
//
        //编写一个Java程序，实现Fibonacci数列的前n项计算，并输出结果。
        /*斐波那契数列是一个整数序列，其中每个数都是前两个数之和。数列的前两个数通常是0和1。斐波那契数列的定义如下：
            F(0) = 0
            F(1) = 1
            F(n) = F(n-1) + F(n-2) (对于n > 1)
                                1  2  3  4  5  6  7  8   9   10
        因此，斐波那契数列的前几项是：0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
        */
        Scanner scanner = new Scanner(System.in);
        System.out.println("您需要计算斐波那契数列的前几项呢？请您输入😊😊");
        long n = scanner.nextLong();
        long result = fic(n);
        System.out.println("您要计算的前"+n+"项斐波那契数列和为:"+result);
    }
    public static long fic(long n) {
        long current = 1;
        long previous = 0;
        long next = 0;
        if (n == 1) {//注意，斐波那契数列的递归式是从n=2开始的，斐波那契数列的第一项1，从第二项开始才有递归规律
            return next;
        } else {
            for (long i = 2; i <= n; i++) {//注意这里i的初始值
                next = current + previous;
                current = previous;
                previous = next;
            }
            return next;
        }
    }
}

